現在每次發送訊息的時候,訊息區塊雖然會出現scrollbar,但都只會停在最上面,今天就來處理這件事r
因為我們需要抓到DOM的高度來做計算,會用到ref的屬性
ref="name"
this.$refs.name就可以抓到DOM嚕在nuxt的
asyncData中是抓不到ref的,因為執行asyncData時,DOM尚未被渲染出來,所以抓不到
<div
    class="chat_main"
    ref="chat_main"
  >
    <div class="channel_tab">...</div>
    // ...略
</div>
如果切版是延續十號坑,需要改一下切法Orz,因為要抓的DOM在原本的寫法會在layout那層,為了容易讀,所以我把這塊切版改到chat頁做
計算滑到最下方
scrollBottom() {
    let dom = this.$refs.chat_main
    dom.scrollTop = dom.scrollHeight - dom.clientHeight
  }
然後在更新對話資料之後執行
uploadMsg(msg) {
    this.allMsg.push(msg)
    this.scrollBottom()
  },
雖然理論上是這樣沒錯,但這邊會遇到一個問題,就是執行scrollBottom的時候抓到的DOM高度還是舊的,我們的對話內容是v-for渲染出來,但執行速度上,v-for還沒渲染完,scrollBottom就去抓了高度,所以計算出來會少一次對話的高度
目前為了要確認是在畫面渲染之後才執行scrollBottom,我改在對話component:codeClassFunc跟codeClassHtml的mounted去觸發,也就是當對話被建立之後才觸發,不過還需要另外處理一些東西,像是當是別人發的對話的時候不觸發,只有自己發的訊息才觸發之類的
然後因為改到子層才觸發,所以需要用到$emit
先在templete綁定事件
<div
  v-for="chat in channels.now.msg"
  :key="chat.key + chat.text"
>
  <component
    :is="chat.codeClass"
    :text="chat.text"
    :name="chat.name"
    @scrollBottom="scrollBottom" // 將scrollBottom綁上去
  />
</div>
然後再下一層就可以用emit去觸發上一層的事件
this.$emit('scrollBottom')